<!--*************************************
* @update:  2021-06-24  LiLinBin  [创建文件]
* @update:  2021-06-24  LiLinBin  [编写功能]
* 
* @description: 组件的事件配置
****************************************-->
 
<template>
    <div class='event-config'>
        <a-collapse v-model:activeKey="activeKey"
            :accordion="true">
            <a-collapse-panel key="1"
                header="监听事件">
                <!-- @change="changeOnEventStr" -->
                <a-textarea v-model:value="onEventStr"
                    @focus="openCodeMr('onEventStr')"
                    :disabled="disableFocus"
                    placeholder="例如:eventBus.on('chart/bar/basePie.vue', (params) => {})"
                    :rows="10" />
                <!-- 按钮 -->
                <!-- <a-row class="mt-20">
                    <a-col :span="8"
                        :offset="16">
                        <a-button type="primary"
                            :disabled="disOnEventBtn"
                            @click="startOnEvent">保存修改</a-button>
                    </a-col>
                </a-row> -->
            </a-collapse-panel>

            <a-collapse-panel key="2"
                header="发送事件">
                <!-- @change="changeEmitEventStr" -->
                <a-textarea v-model:value="emitEventStr"
                    @focus="openCodeMr('emitEventStr')"
                    :disabled="disableFocus"
                    placeholder="例如: eventBus.emit('chart/bar/basePie.vue', {params: '我是参数'})"
                    :rows="4" />
                <!-- 按钮 -->
                <!-- <a-row class="mt-20">
                    <a-col :span="8"
                        :offset="16">
                        <a-button type="primary"
                            :disabled="disEmitEventBtn"
                            @click="emitEvent">保存修改</a-button>
                    </a-col>
                </a-row> -->
            </a-collapse-panel>

            <a-collapse-panel key="3"
                header="交互脚本">
                <!-- @change="changeMixinStr" -->
                <a-textarea v-model:value="mixinStr"
                    placeholder="mixin对象"
                    @focus="openCodeMr('mixinStr')"
                    :disabled="disableFocus"
                    :rows="20" />
                <!-- 按钮 -->
                <!-- <a-row class="mt-20">
                    <a-col :span="8"
                        :offset="16">
                        <a-button type="primary"
                            :disabled="disMixinStrBtn"
                            @click="loadCustomMixin">保存修改</a-button>
                    </a-col>
                </a-row> -->
            </a-collapse-panel>

            <a-collapse-panel key="4"
                header="提示说明">
                <div ref="tipWrapper">
                    <a-textarea :value="curTip.text"
                        readonly
                        placeholder="提示说明"
                        :rows="curTip.rows" />
                </div>

                <a-row class="mt-10">
                    <a-col :span="16">
                        <a-button :type="curTip.id==='tip' ? 'primary' : 'default'"
                            class="custom-btn"
                            @click="curTip=tips[0]">查看'提示说明'</a-button>
                    </a-col>
                </a-row>

                <a-row class="mt-10">
                    <a-col :span="16">
                        <a-button :type="curTip.id==='onEvent' ? 'primary' : 'default'"
                            class="custom-btn"
                            @click="curTip=tips[1]">查看'监听事件'代码案例</a-button>
                    </a-col>
                    <a-col :span="6"
                        :offset="2">
                        <a-button @click="copyCody('onEvent')">复制</a-button>
                    </a-col>
                </a-row>

                <a-row class="mt-10">
                    <a-col :span="16">
                        <a-button :type="curTip.id==='emitEvent' ? 'primary' : 'default'"
                            class="custom-btn"
                            @click="curTip=tips[2]">查看'发送事件'代码案例</a-button>
                    </a-col>
                    <a-col :span="6"
                        :offset="2">
                        <a-button @click="copyCody('emitEvent')">复制</a-button>
                    </a-col>
                </a-row>

                <a-row class="mt-10">
                    <a-col :span="16">
                        <a-button :type="curTip.id==='js' ? 'primary' : 'default'"
                            class="custom-btn"
                            @click="curTip=tips[3]">查看'交互脚本'代码案例</a-button>
                    </a-col>
                    <a-col :span="6"
                        :offset="2">
                        <a-button @click="copyCody('js')">复制</a-button>
                    </a-col>
                </a-row>
            </a-collapse-panel>
        </a-collapse>

        <!-- <teleport to="body">
            <VueDragResize :w="700"
                :h="820"
                :x="550"
                :y="70"
                :minw="100"
                :minh="100"
                v-if="showCodeMr"
                :isDraggable="isDraggable">
                <div @mousedown="dragCodeMr"
                    style="width:100%;height:100%">
                    <codemirrorEditor :codeValue="codeValue"
                        @cancelEdit="cancelEdit"
                        @saveEdit="saveEdit"></codemirrorEditor>
                </div>
            </VueDragResize>
        </teleport> -->
    </div>
</template>

<script>
// import VueDragResize from 'vue-drag-resize';
// import codemirrorEditor from './4_codemirrorEditor'
import attrConfigMixin from 'tools/mixins/1_attrConfigMixin'

export default {
    des: '组件的事件配置',
    name: 'eventConfig',
    components: {
        // VueDragResize,
        // codemirrorEditor
    },
    mixins: [attrConfigMixin],
    props: {
        //接收传递过来的eventConf
        eventConfig: {
            type: Object,
            default: () => ({})
        }
    },
    setup(props, { attrs, slots, emit }) { },
    data() {
        return {
            width: '300px',
            activeKey: ["1"],

            isDraggable: true,
            showCodeMr: false,
            codeValue: '',

            disOnEventBtn: true,
            disEmitEventBtn: true,
            disMixinStrBtn: true,

            onEventStr: '',
            emitEventStr: '',
            mixinStr: '',

            myEventConfig: {},

            oldOnEvntType: '', //上一次监听的事件类型
            oldOnEventHandler: null,

            //提示说明
            tips: [],
            curTip: {},

            disableFocus: false,    //禁止再次聚焦
            editType: ''    //当前代码编辑的类型['监听事件','交互脚本']
        }
    },
    computed: {},
    watch: {
        eventConfig: {
            handler() {
                this.resetMixinStr()
                this.initData()
            },
            deep: true
        }
    },
    created() {
    },
    mounted() {
        this.init()
    },
    activated() { },
    methods: {
        init() {
            this.initTip()
            this.initData()
        },


        dragCodeMr(e) {
            const eTarget = e.target
            if (eTarget.classList.contains('CodeMirror-gutter') || eTarget.classList.contains('title')) {
                this.isDraggable = true
            } else {
                this.isDraggable = false
            }
        },


        //打开代码编辑器
        openCodeMr(editType) {
            if (this.editType === editType) return
            this.editType = editType

            if (this.editType === 'mixinStr') {
                this.codeValue = this.mixinStr
            } else if (this.editType === 'onEventStr') {
                this.codeValue = this.onEventStr
            } else if (this.editType === 'emitEventStr') {
                this.codeValue = this.emitEventStr
            }

            this.showCodeMr = true
            this.disableFocus = true
        },


        //关闭代码编辑
        cancelEdit() {
            this.editType = ''
            this.showCodeMr = false
            this.disableFocus = false
        },


        //保存代码编辑
        saveEdit(newCode) {
            if (this.editType === 'mixinStr') {
                this.mixinStr = newCode
                this.loadCustomMixin() //加载脚本mixin
            } else if (this.editType === 'onEventStr') {
                this.onEventStr = newCode
                this.startOnEvent()
            } else if (this.editType === 'emitEventStr') {
                this.emitEventStr = newCode
                this.emitEvent()
            }

            this.cancelEdit()
        },

        //恢复重置
        resetMixinStr() {
            if (!this.mixinStr.trim()) return

            try {
                const myMixinObj = (new Function("return " + this.mixinStr))()

                if (!myMixinObj) return

                if (myMixinObj.data) {
                    let data = null
                    if (_.isFunction(myMixinObj.data)) {
                        data = myMixinObj.data()
                    } else {
                        data = myMixinObj.data
                    }
                    for (let key in data) {
                        this.$data[key] = undefined
                    }
                }

                if (myMixinObj.methods) {
                    for (let key in myMixinObj.methods) {
                        this[key] = undefined
                    }
                }
            } catch (err) {

            }
        },


        initData() {
            const eventConf = this.eventConfig || {}
            this.onEventStr = eventConf.onEventStr || ''
            this.emitEventStr = eventConf.emitEventStr || ''
            this.mixinStr = eventConf.mixinStr || ''

            this.myEventConfig = _.cloneDeep(eventConf)
        },


        //修改了onEventStr
        changeOnEventStr() {
            if (this.onEventStr !== this.myEventConfig.onEventStr) {
                this.disOnEventBtn = false
            } else {
                this.disOnEventBtn = true
            }
        },


        //修改了emitEventStr
        changeEmitEventStr() {
            if (this.emitEventStr !== this.myEventConfig.emitEventStr) {
                this.disEmitEventBtn = false
            } else {
                this.disEmitEventBtn = true
            }
        },


        //修改了mixinStr脚本
        changeMixinStr() {
            if (this.mixinStr !== this.myEventConfig.mixinStr) {
                this.disMixinStrBtn = false
            } else {
                this.disMixinStrBtn = true
            }
        },


        //保存修改 开始监听
        startOnEvent() {
            const onEventStr = this.onEventStr.trim() //复制一份
            this.myEventConfig.onEventStr = onEventStr

            if (!onEventStr) return

            if (this.oldOnEvntType) {
                //已经点击'保存修改 '一次后,避免多次监听,或避免重复监听
                eventBus.off(this.oldOnEvntType, this.oldOnEventHandler)
            }

            const arr = onEventStr.match(/eventBus.on\(["|'](\S+)["|']/)
            if (!arr) {
                this.$message.error('您填写的监听事件存在语法错误! 请修改!')
                return
            }

            const eventName = arr[1]

            try {
                //执行
                eval(onEventStr)
                //保存
                this.oldOnEvntType = eventName
                this.oldOnEventHandler = eventBus.all.get(this.oldOnEvntType).slice(-1)[0]

                // this.myEventConfig.onEventStr = onEventStr
            } catch (err) {
                console.log('\n')
                console.warn('执行eval监听事件报错:', err)
                console.log('\n')
            }
        },

        //派发事件
        emitEvent() {
            const emitEventStr = this.emitEventStr.trim() //复制一份
            this.myEventConfig.emitEventStr = emitEventStr

            if (!emitEventStr) return

            const arr = emitEventStr.match(/eventBus.emit\(["|'](\S+)["|']/)
            if (!arr) {
                this.$message.error('您填写的派发事件存在语法错误! 请修改!')
                return
            }

            const eventName = arr[1]
            const onFns = eventBus.all.get(eventName)

            if (!onFns || onFns.length === 0) {
                this.$message.warn('提示:还没有注册此事件的监听,即不会有响应!')
                return
            }

            try {
                //执行
                eval(emitEventStr)
                // this.myEventConfig.emitEventStr = emitEventStr
            } catch (err) {
                console.log('\n')
                console.warn('执行eval事件派发报错:', err)
                console.log('\n')
            }
        },

        //加载脚本mixin
        loadCustomMixin() {
            const mixinStr = this.mixinStr.trim()
            this.myEventConfig.mixinStr = mixinStr

            if (!mixinStr) return

            let myMixinObj = null
            try {
                myMixinObj = (new Function("return " + mixinStr))()
            } catch (err) {
                this.$message.error('脚本的格式或语法错误,请修改!详细见控制台输出.')
                console.warn('执行脚本出错:', err)
            }

            if (!myMixinObj) return

            if (myMixinObj.data) {
                let data = null
                if (_.isFunction(myMixinObj.data)) {
                    data = myMixinObj.data()
                } else {
                    data = myMixinObj.data
                }
                for (let key in data) {
                    this.$data[key] = data[key]
                }
            }

            if (myMixinObj.methods) {
                for (let key in myMixinObj.methods) {
                    this[key] = myMixinObj.methods[key]
                }
            }

            this.initMyJs && this.initMyJs()

            // this.myEventConfig.mixinStr = mixinStr

            /* 
            {
                data: () => {
                    return {
                        myAbc: "加鸡腿"
                    }
                },
                methods: {
                    //初始时执行
                    initMyJs() {
                        this.doThingA()
                    },

                    doThingA() {
                        alert("读取组件中的变量: " + this.activeKey);
                        alert("读取自己mixin中的变量: " + this.myAbc);
                    },

                    //销毁一些定时器等等
                    destroyMyJs() {}
                }
            } 
           */
        },


        //复制案例代码
        copyCody(id) {
            // this.$refs.tipWrapper.querySelector('textarea').select()
            // document.execCommand('copy', false); // copy已经选中的内容
            const text = this.tips.find(o => o.id === id).text
            navigator.clipboard.writeText(text)
            this.$message.success('复制成功!')
        },

        //初始化"提示说明"
        initTip() {
            this.tips = [
                {
                    id: "tip",
                    rows: 11,
                    text: [
                        '1. echarts库,全局变量可直接使用,如: echarts.init();',
                        '2. axios数据请求库,全局变量;',
                        '3. eventBus事件总线机制,全局变量;',
                        '4. 注入脚本的入口函数名需为: initMyJs();',
                        '5. 注入脚本的销毁函数名需为: destroyMyJs();',
                        '6. findComp.call(this, xxxxx[组件标识]),可找到当前页面上指定的组件实例对象;'
                    ].join('\n')
                },
                {
                    id: "onEvent",
                    rows: 10,
                    text: "eventBus.on(\"chart/pie/basePie.vue\", ({ params }) => { \n\nconsole.log('传递的参数是: ' + params) ;\nconst target = findComp.call(this,'基础柱形图_chartBarBase_93c5c6');\ntarget.drawChart();\n\n    })"
                },
                {
                    id: "emitEvent",
                    rows: 5,
                    text: `eventBus.emit("chart/pie/basePie.vue", { params: '我是参数,成功了,加鸡腿呀!!!' })`
                },
                {
                    id: "js",
                    rows: 20,
                    text: "{\n    data: () => {\n        return {\n            myAbc: \"加鸡腿\"\n        }\n    },\n    methods: {\n        initMyJs() {\n                this.doThingA()\n        },\n\n        doThingA() {\n\nconst target = findComp.call(this,'基础柱形图_chartBarBase_93c5c6');\ntarget.drawChart();\n\n        },\n\n        //销毁一些定时器等等\n        destroyMyJs() {}\n    }\n}"
                }
            ]

            this.curTip = this.tips[0]
        }
    },
    deactivated() { },
    beforeUnmount() {
        this.editType = ''
        this.$message.destroy()
        eventBus.off(this.oldOnEvntType, this.oldOnEventHandler)
        this.destroyMyJs && this.destroyMyJs() //销毁注入的脚本
    }
};
</script>

<style lang="less">
.event-config {
    width: 100%;
    height: 100%;
    .custom-btn {
        display: block;
        width: 100%;
    }
}
</style>